﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

namespace DimensionsHelper.Common.Contracts.Metadata;

/// <summary>
///     描述MDM数据文档的数据链接定义。
/// </summary>
public interface IDataSource : IMetadataNamedObject
{
    /// <summary>
    ///     数据库文件路径。
    /// </summary>
    string DbLocation { get; }

    /// <summary>
    ///     Cdsc
    /// </summary>
    string Cdsc { get; }

    /// <summary>
    ///     项目名
    /// </summary>
    string Project { get; }

    /// <summary>
    ///     链接Id，文档范围内唯一。
    /// </summary>
    string Id { get; }

    /// <summary>
    ///     原始数据变量对照表。
    /// </summary>
    IAliasMap AliasMap { get; }
}

/// <summary>
///     MDM数据文档的数据源链接集合定义。
/// </summary>
public interface IDataSources : IMetadataStringKeyCollection<IDataSource>, IMetadataObject
{
    /// <summary>
    ///     默认使用的数据链接名。
    /// </summary>
    string DefaultName { get; }

    /// <summary>
    ///     默认的数据链接。
    /// </summary>
    IDataSource Default { get; }
}

/// <summary>
///     用于保存XML文档中Tag是nativevalue的节点内容。
/// </summary>
public class NativeValue(string fullName, string value)
{
    public string FullName { get; } = fullName;

    public string Value { get; } = value;
}

/// <summary>
///     用于保存XML文档中Tag是subalias的节点内容。
/// </summary>
public class SubAlias(int index, string name)
{
    public int Index { get; } = index;

    public string Name { get; } = name;
}

/// <summary>
///     存储元数据转换前的变量信息，XML中Tag是var
/// </summary>
public interface IAlias : IEnumerable<SubAlias>
{
    /// <summary>
    ///     本地变量全名
    /// </summary>
    string FullName { get; }

    /// <summary>
    ///     本地变量别名
    /// </summary>
    string AliasName { get; }

    /// <summary>
    ///     属性配置集合，可以不添加属性。
    /// </summary>
    IProperties Properties { get; }

    /// <summary>
    ///     数据是通过转换其他类型元数据得来得时候，此值表示原始值。
    ///     XML中Tag是nativevalues。
    /// </summary>
    IReadOnlyList<NativeValue> NativeValues { get; }

    /// <summary>
    ///     通过索引获取成员对象。
    /// </summary>
    /// <param name="index">指定索引</param>
    /// <returns>指定索引的成员对象</returns>
    /// <exception cref="IndexOutOfRangeException" />
    SubAlias this[int index] { get; }

    /// <summary>
    ///     添加新的SubAlias。
    /// </summary>
    /// <param name="index">索引</param>
    /// <param name="name">名称</param>
    bool AddSubAlias(int index, string name);

    /// <summary>
    ///     尝试依据给定名称查找已有的下级别名定义。
    /// </summary>
    /// <param name="name">查找的名称，不区分大小写</param>
    /// <param name="subAlias">当前别名定义的下级别名定义</param>
    /// <returns>如果给定名称存在，返回true，否则，返回false</returns>
    bool TryGetSubAliasByName(string name, [MaybeNullWhen(false)] out SubAlias subAlias);

    /// <summary>
    ///     尝试依据索引查找已有的下级别名定义。
    /// </summary>
    /// <param name="index">下级索引</param>
    /// <param name="subAlias">当前别名定义的下级别名定义</param>
    /// <returns>如果给定索引存在，返回true，否则，返回false</returns>
    bool TryGetSubAliasByIndex(int index, [MaybeNullWhen(false)] out SubAlias subAlias);

    /// <summary>
    ///     添加新的本地值
    /// </summary>
    /// <param name="fullName">IElement元素全名</param>
    /// <param name="value">IElement元素值</param>
    /// <returns>如果给定值和名称不重复，返回true，否则，返回false</returns>
    bool AddNativeValue(string fullName, string value);

    /// <summary>
    ///     尝试依据给定名称获取已有的本地值配置对象。
    /// </summary>
    /// <param name="fullName">查找的元素名，不区分大小写</param>
    /// <param name="nativeValue">已读取的本地值</param>
    /// <returns>如果给定名称存在，返回true，否则，返回false</returns>
    bool TryGetNativeValueByName(string fullName, [MaybeNullWhen(false)] out NativeValue nativeValue);

    /// <summary>
    ///     尝试依据给定值获取已有的本地值配置对象。
    /// </summary>
    /// <param name="value">查找的元素值，不区分大小写</param>
    /// <param name="nativeValue">已读取的本地值</param>
    /// <returns>如果给定值存在，返回true，否则，返回false</returns>
    bool TryGetNativeValueByValue(string value, [MaybeNullWhen(false)] out NativeValue nativeValue);
}

/// <summary>
///     <see cref="IAlias" />类型元素组成的列表，各个元素是在connection tag下的var tag节点内容。
/// </summary>
public interface IAliasMap : IMetadataObject, IEnumerable<IAlias>
{
    /// <summary>
    ///     集合中的数量
    /// </summary>
    int Count { get; }

    /// <summary>
    ///     向集合末尾添加一个新的<see cref="IAlias" />对象。
    /// </summary>
    /// <returns></returns>
    IAlias AddNew(string fullName, string aliasName);

    /// <summary>
    ///     获取变量别名配置。
    /// </summary>
    /// <param name="fullName">变量全名</param>
    /// <returns>如果给定变量名存在，返回已有对象，否则，返回null</returns>
    IAlias? Get(string fullName);

    /// <summary>
    ///     尝试获取变量别名配置。
    /// </summary>
    /// <param name="fullName">变量全名</param>
    /// <param name="alias">变量别名配置</param>
    bool TryGet(string fullName, [MaybeNullWhen(false)] out IAlias alias);
}